package syncx

import (
	"fmt"
	"sync"
	"time"
)

// IDManager 管理多个共享资源的细粒度访问
type IDManager struct {
	// 资源映射表
	IDs map[string]int

	// 每个资源有自己独立的锁
	locks map[string]*sync.RWMutex

	// 保护锁映射表本身的全局锁
	globalLock sync.RWMutex
}

// NewIDManager 创建新的资源管理器
func NewIDManager() *IDManager {
	return &IDManager{
		IDs:   make(map[string]int),
		locks: make(map[string]*sync.RWMutex),
	}
}

// 获取指定资源的锁，如果不存在则创建
func (rm *IDManager) getLock(id string) *sync.RWMutex {
	// 先以读锁检查是否已存在锁
	rm.globalLock.RLock()
	lock, exists := rm.locks[id]
	rm.globalLock.RUnlock()

	if exists {
		return lock
	}

	// 不存在则创建新锁（需要写锁）
	rm.globalLock.Lock()
	defer rm.globalLock.Unlock()

	// 双重检查，避免在获取写锁期间其他goroutine已创建了锁
	lock, exists = rm.locks[id]
	if !exists {
		lock = &sync.RWMutex{}
		rm.locks[id] = lock
	}

	return lock
}

// UpdateID 更新特定资源（写操作）
func (rm *IDManager) UpdateID(id string, value int) {
	// 获取该资源的专用锁
	lock := rm.getLock(id)

	// 锁定特定资源
	lock.Lock()
	defer lock.Unlock()

	fmt.Printf("正在更新资源 %s = %d\n", id, value)
	time.Sleep(time.Second) // 模拟耗时操作

	// 更新资源
	rm.IDs[id] = value
	fmt.Printf("资源 %s 更新完成\n", id)
}

// GetID 获取特定资源值（读操作）
func (rm *IDManager) GetID(id string) (int, bool) {
	// 获取该资源的专用锁
	lock := rm.getLock(id)

	// 对特定资源加读锁
	lock.RLock()
	defer lock.RUnlock()

	// 检查资源是否存在
	rm.globalLock.RLock()
	value, exists := rm.IDs[id]
	rm.globalLock.RUnlock()

	return value, exists
}
